#include <QQuaternion>
#include "AnimMontageUtils.h"
#include "PoseBlend.h"
#include "BlendAttached.h"

PoseBlend::PoseBlend()
{

}

template<typename T>
void blendValue(const T&vb,T& v1,const T&v2,float alpha){
    if(!vb)
    {
        return;
    }

    if(!v1 && !v2)
    {
        return;
    }
    else if(!v1)
    {
        v1 = AnimMontageUtils::inter(vb.value(),v2.value(),alpha);
    }
    else if(!v2)
    {
        v1 = AnimMontageUtils::inter(v1.value(),vb.value(),alpha);
    }
    else{
        v1 = AnimMontageUtils::inter(v1.value(),v2.value(),alpha);
    }
}

//混合两种姿态
static void blendEntrys(const Pose& base,Pose& e1,const Pose& e2,float alpha,const QStringList &nodeList){

    QSet<QByteArray> names;
    for(const auto &key:e1.keys())
    {
        names.insert(key);
    }
    for(const auto &key:e2.keys())
    {
        names.insert(key);
    }

    for(const auto &key:names)//只有二者都有的对象才会参与融合
    {
        if(!nodeList.isEmpty() && !nodeList.contains(key))//被nodelist排除的不参与融合
        {
            continue;
        }

        auto vb = base.value(key),v2 = e2.value(key);
        auto& v1 = e1[key];
        auto old = v1.rotation;
        blendValue(vb.position,v1.position,v2.position,alpha);
        blendValue(vb.rotation,v1.rotation,v2.rotation,alpha);
        blendValue(vb.scale,v1.scale,v2.scale,alpha);
    }
}

template<typename T>
void setValue(T& v1,T& v2){
    if(v2)
    {
        v1 = v2;
    }
}

Pose PoseBlend::getEntry()
{
    Pose base;
    Pose ret;
    PoseNode* baseNode = nullptr;

    for(auto i:childItems())
    {
        auto node = qobject_cast<PoseNode*>(i);

        if(!node)
        {
            continue;
        }

        if(baseNode)
        {
            auto addon = node->getEntry();

            float alpha = 0;
            QStringList nodeList;

            auto att = qobject_cast<BlendAttached*>(qmlAttachedPropertiesObject<Blend>(node,false));

            if(att)
            {
                alpha = att->alpha();
                nodeList = att->getNodeList();
            }
            blendEntrys(base,ret,addon,alpha,nodeList);
        }
        else{//第一个姿态节点为基本姿态
            baseNode = node;
            base = baseNode->getEntry();
        }
    }

    for(const auto &i:ret.keys())
    {
        auto& o1 = base[i];
        auto& o2 = ret[i];
        setValue(o1.position,o2.position);
        setValue(o1.rotation,o2.rotation);
        setValue(o1.scale,o2.scale);
    }

    return base;
}
